AYA (文) Version 5 說明文書 †何謂AYA †AYA的日文即「あや」,漢字是「文」,由 umeiciさん 製作的高機能SHIORI,由於採用近似於C語言的寫法,對於學過程式語言的人而言,特別容易上手。而對於沒有相關背景的人格開發者,AYA的作者也提供了基礎的人格範本*1,只要經過少量的修改,便能成為一個全新的人格。 AYA主要執行下述處理:
環境 †Windows用。 開發的初期版本有經過98SE、2000、xp的動作確認,不過最終版本並沒有在XP以外的系統上作過動作確認。 使用規定 †利用規定(作者原文)
匯出的函式 †文有以下被公開的函式。 extern "C" __declspec(dllexport) BOOL __cdecl load(HGLOBAL h, long len) 文初期化指示。 extern "C" __declspec(dllexport) BOOL __cdecl unload() 文終了指示。 extern "C" __declspec(dllexport) HGLOBAL __cdecl request(HGLOBAL h, long *len) 文に処理を指示し、結果を得ます。 此外,這部份和桌面應用軟體「伺か」使用的擬似AI用DLL「SHIORI」的介面規格完全是相同的。 基礎設定 †文 ver.5的預設DLL檔名為「aya5.dll」。 為了讓文正常作動,被稱為「基礎設定檔案」的檔案是必要的。 基礎設定檔案為TEXT文件、實行時以OS預設的文字編碼來解讀。 以下述為例: // dics dic, basis.dic dic, control./*doc*/ayc // option parameters charset, UTF-8 charset.dic, Shift_JIS charset.output, UTF-8 charset.file, Shift_JIS charset.save, UTF-8 charset.extension, Shift_JIS msglang, english log, executelog.txt iolog, off fncdepth, 16 設定時用逗號劃分命令和參數。 空行(只換行的行)、『//』後面單行文字、『/*』到『*/』包圍的範圍皆不會被讀取。 命令和其意義為如下所示:
AYA腳本參照 †AYA腳本大致上的語法抄襲自C語言。 若曾學過C語言,在學習類似於C語言的AYA時便易於理解。 函式 †基礎 †以下為request實行時能傳回字串"Hello World"的代碼。 request { "Hello World" } 文讀取此模組 HGLOBAL request(HGLOBAL h, long *len) ,實行此腳本後,便傳回"Hello World"。 load與unload是同樣的。 只要寫必要的函式就好。不必要的則可省略。 load和request有一個參數。可以用變數取出此值。 _argc †參數的數量。load和request的參數是一個字串,所以值為1。unload沒有參數、因此值為0。 _argv †參數的實體存在此處。此為具有_argc個元素的陣列。各元素中的存取位址為運算子[i]。 總結基礎編的內容,load 將 "Hello" 收納進變數str, request 將作為參數交出的字串與 str 結合後傳回的程式碼顯示出來。 請以上述的說明為基礎讀讀看。 load { str = "World" } request { str + "Hello" + _argv[0] + "!" } 將處理對象字串設為"World"交予 request 實行,可以得到 "Hello World!" 的結果。 語法 †有以下之例:
也就是說先前舉例的Hello World代碼可以下列方式寫在一行之中。 request{"Hello World"} 那麼像以下這樣的寫法可以嗎? 當然。運算上不會有問題。 req/ uest { "/ Hello World" } 斜線"/"的下一行(被重新結合的行)先頭的空白文字會被判定為無效文字而消除。 "ABCD EFG" 第4項説明。 request { answer = 1 + 2 "答案是" + answer + "的樣子。" } 用分號的話可以寫成以下這樣。 request { answer = 1 + 2; "答案是" + answer + "的樣子。" } 分號過多時不會造成問題。它們會被無視,不影響運算的結果。 自定義函式的定義與實行 †除了 load、unload、request 以外也可以製作你自行取名的函式。 request { hello } hello { "Hello World" } 上面表示的是最單純的例子。request的結果會傳回"Hello World"。 為了完成一些工作,大部份的函式會需要一個或者是更多的參數(parameter),而參數是讓你可以傳遞一些資料到函式中。以下的例子可以得到與上述例子同樣的結果。 request { combine("Hello", "World") } combine { _argv[0] + " " + _argv[1] } 函式名後面加入( ),並在內部以逗號分列數值,這樣一來這些值會作為參數交給該函式。即作為變數_argv和_argc的值,可在此函式内被提取。 函式名可以自由取名,但不能與下列的規則相扺觸。
函式重複呼叫是可能的。 request { factorial(5) } factorial { if !_argv[0] 1 else factorial(_argv[0] - 1)*_argv[0] } request傳回120。 字串選擇 †request { "Hello World" "你好世界" "Hallo Welt" } 像這樣的例子的話、這三個句子會被視為同等的「輸出候補」、輸出三者之中的任意一個。 一共有5種選擇方法,可以任意選擇其中一種。 不指定 †預設為隨機選擇。 nonoverlap †在所有的候補都被選過之前,不會選擇重複的選項。 request : nonoverlap { "Hello World" "你好世界" "Hallo Welt" } 像上列這樣在函式後面附加": nonoverlap"。 sequential †上至下按順予輸出。輸出到最後時,會返回先頭。 request : sequential { "Hello World" "你好世界" "Hallo Welt" } 像上列這樣在函式後面附加": sequential"。 void †什麼都不輸出。 request : void { "Hello World" "你好世界" "Hallo Welt" } 「什麼都不做」與「什麼都不輸出」之間的差別請注意一下。 increment_i : void { i++ i } 上列函式中increment_i的i會進行1的加算。在沒有void的場合下、此函式會傳回加算的結果、在有指定void的場合下,不會傳回任何的值,僅只是進行了加算的動作。 array †輸出候補會全部集成一個泛用陣列作為函式的返値。 request : array { "This is a pen." ("A","B","C") 3.14 } 輸出結果等同於泛用陣列 ("This is a pen.", "A", "B", "C", 3.14) 。 nonoverlap和sequential即使在具有輸出確定子的情況下,也能取得所有的組合進行正常的運作。 request : sequential { "1" "2" "3" -- "A" "B" } request會照以下順序輸出。 "1A" "2A" "3A" "1B" "2B" "3B" "1A" "2A" … 有時函式會使輸出候補數量產生變動。 request : sequential { if i { "1" "2" } "3" "4" } 當候補數產生變化後、nonoverlap和sequential的巡迴順序會初期化,重新回到一開始的狀態。唯有此時才有可能輸出和上回相同的值。 子階層{} †request { { "Hello World" "你好世界" } "Hallo Welt" } { } 可以階層式的重複書寫。其中變化與最高層的{ }相同,會在包含其中的候補挑選一個輸出。 從上述來看,{ }的有無似乎是一樣的,但實際上不是這樣。 輸出確定子 †request { "Hello" "Perfect" "Peaceful" -- " Wor" -- "ld" "th" } 『--』作為輸出確定子,會將選擇候補的範圍切開來分成各自的小組。然後,將各小組選出來的結果互相結合。 "Hello World" "Perfect World" "Peaceful World" "Hello Worth" "Perfect Worth" "Peaceful Worth" 與nonoverlap、sequential組合使用的場合下,(グループ單位ではなく)函式會根據取得的所有組合進行相對的動作。 輸出確定子在任何地方都可使用,即使在{ }很深的情況下。 文也能處理同時有字串與數値的情況。 値與變數 †即値 †文能處理的值為整數、實數、字串3種類。
int10 { 10 0b1010 0xa }
變數 †變數為保存值的領域。
上述的這幾種。 名字在不觸犯以下禁止條款的前提下可自由設置。
値的保存(指派)由指派運算子 = 來執行。要輸出内容的話、與函式一樣寫下變數的名字即可。 request { str = "你好" str } 上面為最單純的例子、變數str存取字串、並照著那樣輸出。 若是未指派值的變數,則會輸出空的字串。 request { "Hello World" i } i 並不存在,因此為空的字串,結果上面的例子與下面的寫法等價,因此有1/2的機率會輸出"Hello World"或空字串。 request { "Hello World" "" } 變數的範圍與壽命 †變數有兩種不同的scope(有效範圍)。
兩者的區別為變數的名字。變數名前頭有下標線("_")的變數為區域變數。 request { _i = "3*2等於" _j = multi(3) _i +_j + "的樣子" } multi { _i = _argv[0] _i * 2 } request與multi雖然使用了同樣名字的變數 _i,但兩者被視為完全無關的值來運算,也不會互相干擾。 你或許也察覺到函式的參數所使用的變數_argc和_argv同樣也是區域變數。 區域變數並非是「在現在的函式内可以使用的變數」,而是「現在的{ }内、甚至更深的階層都可使用的變數」,這點請注意一下。 request { { _str = "Hello World" } _str } 這個程式無法照著我們希望的那樣動作。 request { _str = "" { _str = "Hello World" } _str } 全域變數與區域變數的差異就在這裡。就是壽命。 運算 †基本 †與C語言同様寫法的四則運算、比較運算、指派、及其他可能的運算。 運算子的種類與演算優先度如下。
(註)論理和為 || 附有冒號(":")的指派運算子乃因舊有版本的相容性而保留的,功能上與沒有冒號的指派運算子完全相同。 *為單項運算子。 括弧( )相關內容會在次項中詳細說明。 _in_與!_in_為字串中包含校驗功能的運算子。 foo { "or" _in_ "World" } _in_ 若左邊字串在右邊字串中有相符字串的話傳回1、如果沒有的話傳回0。!_in_為相反。 比較運算子的結果是真時傳回整數1、偽時傳回0。 邏輯真偽的判斷。
沒有指派的運算會直接輸出結果。 foo { (3+2)*4 } 此函式foo最後會輸出20。 同樣優先度的運算子連續出現的場合下,通常由左開始結合。 1+2-3 例如上式為 i = j = 10 至於這種例子又怎麼說呢?因為C語言的指派運算子為由右至左的演算,所以 i 與 j 都被指派了10的值。 i = (j = 10) 改成這樣寫的話 i 就可以得到10的值了。 演算對象項目的型別不一致的場合下、最終結果的型別如下列所示。
即使在一個演算式内混合多種的型別也沒關係。 "10+2等於" + (10+2) + "的樣子。" 一開始是10+2的整數計算,得到的值為12。接下來為所有字串的加算,12轉換成字串,作為字串組合在一起。 有括弧( )時的演算順序 †括弧( )包圍的部分為演算順序中最優先展開的。 平白的說就是「從包圍最深的地方先開始計算」。因為這是理所當然的規則,所以也不用特別在意。不過按照數式的寫法也是可以弄得非常複雜的。 answer = (_i = 10) + (2*(_i + 10)) 對於不理解文的演算法則的人來說,很難保證answer會是怎樣的值吧。 最初的計算在哪?括弧最深的地方、也就是 _i + 10 。那麼變數 _i 還不存在,因而變成空字串。再來、_i + 10 為字串與整數的加算。10也變成字串、也就是"10"。但是接下來為與整數的乘算、結果又變成了空字串。 那麼、這邊的意圖首先是讓_i = 10的指派成為最初的演算。 answer = (((_i = 10))) + (2*(_i + 10)) 這樣一來指派的優先度就大為提升。這回應該便能得到正確的結果了。 然而,如果你以為將括弧加到第2層即可的話,那你又錯了。括弧2段的話雖然與 _i + 10同樣深度,但是 = 與 + 相比優先度是 + 的那邊較高。 反饋運算子& †反饋運算子&是用法完全不同於別的運算子的獨特運算子。 request { _i = 1 foo(&_i) } foo { _argv[0] = 100 } 呼叫函式時將變數作為參數的時候、可以在變數的前面加上&。前頭附有&的變數可以與原先叫出函式相對應的_argv的元素產生關聯。也就是說、當_argv的值改變的時候、其對應的原呼叫變數的值也會改變。 反饋運算子可以自由的在不同地方多次使用。 request { foo(1, 2, &_value, "Hello", &_value2) _value + _value2 } foo { _argv[2] = _argv[0] + _argv[1] _argv[4] = _argv[3] + " World" } 函式request最終傳回 "3Hello World" 。 當然的、反饋運算子只能使用在變數上面。 陣列 †運算子[ ]為用於存取陣列元素的運算子。 陣列分為在字串區分元素來擬似陣列型式的「簡易陣列」,以及以逗號區分、詳細列舉陣列元素的「泛用陣列」這兩種類。 簡易陣列 †將字串中含有的逗號視為分隔符號(劃分的符號),並像陣列般進行處理。 request { _a = "this,is,a,pen" _a[1] } request最後輸出"is"。 [ ]運算子處理的對象並不一定是變數,即値與函式的返値也是可以的。 request { "this,is,a,pen"[1] } 在[ ]運算子中的第二項參數可以自行指定分隔符號(delimiter),用逗號以外的文字作為劃分陣列元素的根據。 request { "This,is,a,island."[2,"is"] } 上述即以"is"來進行區分,字串最終會被分解成這樣。 [0] "Th" [1] "," [2] ",a," [3] "land." request因而傳回",a,"。 如果善用分隔符號的話,要做出類似多次元陣列格式的值也是有可能的。 request { _ar = "taro|male,ayame|female,hotaru|female" _ar[2][1,"|"] } _ar[2]即為"hotaru|female"。接下來再將"|"作為劃分文字將"hotaru|female"中的[1]取出的話、結果即為"female"。像這樣每個階層都使用獨特的分隔符號的話,便可以輕鬆取得任意位置的值。 當你指定範圍以外的序數時,會跟取出不存在的變數的情況一樣,傳回的值為空字串。 這邊開始為變數才能使用的功能。 可以指派陣列元素。 request { _a = "this,is,a,pen" _a[3] = "eraser" _a } "pen"會被替換成"eraser"。request的實行結果為"this,is,a,eraser"。 在有指定分隔符號的情況下也能正常運作。 request { _s = "This,is,a,island." _s[2,"is"] = ",beautiful," _s } request會輸出"This,is,beautiful,island."。 在與多次元陣列[ ]運算子連結使用的時候,則無法指派( = )運算子。 request { _ar = "taro|male,ayame|female,hotaru|female" _ar[1][1,"|"] = "male" } 上述式子想把ayame的性別改為male,但卻會發生錯誤。只有在一次元的情況下才能指派。 指派的位置即使超過現有的元素數量也沒關係。分隔符號會自動追加,擴張元素數量。 request { _m = "fuji/asama/tanigawa" _m[5,"/"] = "daisen" _m } request會輸出"fuji/asama/tanigawa///daisen"。 如果使用叫做SETDELIM的函式的話,便能將「預設的分隔符號」從逗號改為其他的字串。 上述例子如果用SETDELIM來寫的話,會變成下面這樣。 request { _m = "fuji/asama/tanigawa" SETDELIM(_m, "/") _m[5] = "daisen" _m } 運行SETDELIM之後,只要寫_m[5]即可。 在與多次元陣列[ ]運算子連結使用的情況下、SETDELIM只對最初的(一次元的)[ ]有効。 泛用陣列 †泛用陣列是可以保存各種不同型別的值的陣列構造。 初期化 †i = (100,"test",-1.5) 用逗號列舉陣列元素並記述。 (i = 100),"test",-1.5 這樣子解釋。 要使陣列呈現無元素狀態的初期化,請使用IARRAY這個函式。IARRAY為會傳回「空的泛用陣列」的函式。 i = IARRAY 初期化時如果只有指派一個陣列元素時得另外做點功夫。假如只有指派i = 100的話,因為不是陣列的關係,會被視為單純的指派100的值。 i = (IARRAY,100) 陣列元素的追加 †i = (i,"add") 這樣寫的話會在陣列i的後端追加"add"這個元素。 也可以追加陣列。 i = (i,("add",123,0.0)) 就像a = a + 1 同等 a += 1這樣的省略法,上述例子也可以寫成像下面這樣。 i ,= ("add",123,0.0) 也可以在陣列的前端插入元素。 i = ("first",i) 也可以在陣列的中間插入元素。 i = (100,200,300,400,500,600) i[2] ,= "insertion" i即為(100,200,300,"insertion",400,500,600)。 i[2] = ("insertion",i[2]) 這樣子寫。 陣列元素的削除 †將要削除的元素指派給IARRAY。 i = (100,200,300,400,500,600) i[2] = IARRAY 300於是被削除、i變成(100,200,400,500,600)。 値的更新 †可以單純的指派元素。 i = (100,200,300,400,500,600) i[2] = 700 i變成(100,200,700,400,500,600)。 指派的位置即使超過現有的元素數量也沒關係。陣列會自動擴張元素數量。 値的取出 †與通常的變數一様,被指定的元素若存在便輸出此陣列元素。 當你指定範圍以外的序數時,會跟取出不存在的變數的情況一樣,傳回的值為空字串。 i = (100,200,300,400,500,600) i[4] 最後輸出500。 [ ]運算子處理的對象並不一定是變數,即値與函式的返値也是可以的。 (100,200,300,400,500,600)[4] 最後輸出500。 泛用陣列也可直接作為函式並輸出。 request { river[2] } river { "tenryu","bandou-tarou","ishikari","shimanto" } request會輸出"ishikari"。 無法多次元化 †泛用陣列無法組合成多次元陣列。 (100,200,(300,400),500,600) 用這樣的寫法時,括弧內包的部份並不會被視為第二次元的陣列。 (100,200,300,400,500,600) 演算 †元素單位的演算一般來說是可以的。 比較獨特的是,泛用陣列的單項値在演算的時候,是 pref = ("gunnma","ohsaka","hokkaido") pref += "-ken" answer = (2*(1,2,3))[1] pref會變成 "gunnma-ken","ohsaka-ken","hokkaido-ken" 。 answer的結果是4。 函式的參數 †在文的體系中,函式的參數為泛用陣列。_argv的內容即為函式呼叫時所代入的參數。 也就是說 func(1, 2, "test") 與這樣的函式呼叫、 _i = (1,2,"test") func(_i) 都可以寫入。這是相當重要的記述。 善用這種構造的話,可以從其他的函式中簡單的取得可變長的參數。 request { total(1,2,3,4,5,6) } total { calc_total(_argv) } calc_total { _answer = 0; foreach _argv; _val { _answer += _val } _answer } total本身完全沒有做什麼事,只是單純的將所有的參數傳給calc_total。 參數的指定方法較為複雜的情況下需要注意幾點。 _i = (1,2,"test") func("sky", _i, "sun") 上述的呼叫與下例同等。使用泛用陣列時請記得它無法多次元化。 func("sky", 1, 2, "test", "sun") 分隔符號/取得數指定 †_i = (2,"is") "This is a island."[_i] 簡易陣列在指定分隔符號的部分也是泛用陣列。所以也能像上述這樣子寫。與下述寫法為等價。 "This is a island."[2,"is"] 範圍指定 †簡易陣列/泛用陣列都可指定序數的範圍,也可以取得或代入。 範圍可用泛用陣列來指定。例如 i[a,b] 可表示為「i的元素a~b」。 name = ("さくら","せりこ","奈留","まゆら","毒子","美耳") i = name[1,3] name[3,4] = "奎子" j = name name[0,2] = IARRAY k = name i變成 ("せりこ","奈留","まゆら") 。 範圍外則自動無視。 n = (1,2,3,4) n[-2,1] *= 5 n為 (5,10,3,4) 。 對象是簡易陣列的時候也是一樣。 name = "さくら,せりこ,奈留,まゆら,毒子,美耳" i = name[1,3] name[3,4] = "奎子" j = name i為 "せりこ,奈留,まゆら" 、jは "さくら,せりこ,奈留,奎子,美耳" 。 指定範圍後再接著指定分隔符號也是可能的。 animal = "熊!兔!貓!狗!鱷" i = animal[0,2,"!"] animal[2,4,"!"] = "豬" j = animal i變成 "熊!兔!貓" ,j變成 "熊!兔!豬" 。 泛用陣列的平行輸出 †所有的式/値的前面都可寫上「parallel」。 foo0 { ("A","B","C") "地球" } foo1 { parallel ("A","B","C") "地球" } foo0的輸出會是("A", "B", "C") 或 "地球"。 把parallel用在泛用陣列以外的值的時候,有寫跟沒寫一樣。例如下面的2種寫法是等價的。 parallel STRLEN("earth") STRLEN("earth") 在使用字串選擇模式array和parallel的時候,可以與函式的輸出候補和泛用陣列互相配合使用。 request { _i = ("甲","乙","丙") cyclic(_i) } cyclic : sequential { parallel _argv } 字串內埋入元素的展開 †可以在字串的中埋入變數或函式,並把實行的結果插入其位置上。 附帶範圍的展開 †將埋入的元素以%( )包圍。 request { _i = "pen" "This is a %(_i)." } request實行後,會輸出"This is a pen."。 %( )會進行類似eval(將字串解釋為Script code並實行)的動作。可以是單一的函式或變數,甚至是算式也沒問題。 request { "1+2+3等於%(1+2+3)。" } request會輸出"1+2+3等於6。"。 請注意,文的字串中無法包含雙引號,因此不能插入含有字串的算式。以下例子會產生錯誤。 request { "This is a %(_i = "pen")." } 像這種時候,要將算式區隔出來。 request { "This is a " + (_i = "pen") + "." } 有括弧( )的演算順序控制與附帶範圍的展開是同様的程序。 request { "行星「%(_i = planet)」離earth很遠。這個行星的顏色是%(color(_i))。" } planet { "mars" "saturn" "pluto" } color { case _argv[0] { when "mars"; "red" when "saturn"; "yerrow" when "pluto"; "blue" others; "unknown" } } 由於最深的( )為color(_i)的參數,所以會在執行_i = planet之前就先呼叫函式color。 "行星「%((_i = planet))」離earth很遠。這個行星的顏色是%(color(_i))。" 這樣一來即可得到沒有矛盾的字串。 名稱最長一致展開 †沒有授與( )時、單純埋入%時所展開的機能。 request { o = "pen" obj = "eraser" object = "world" "This is a %object." } obje { "television" } 其展開的對象為%後面的字串中相符並具有最長一致性的變數/函式。在上面的例子中,一致性最高的變數為object,因而採用此變數。結果會變 成"This is a world.",而不是"This is a televisionct."或"This is a eraserect."。 由於變數時時刻刻都在作成與消失,因此展開的對象也會根據狀況而有所變化。 request { val = "red" trans -- value = "blue" trans } trans { "%value" } trans被實行了兩次,然而第一次與第二次的"%value"的動作是不一樣的。此意味著最初的運行被視為變數val+"ue",第二次則被解釋為變數value。 使用%[ ]語法的話可以呼叫過去的展開結果。 request { "「%planet」很遠。「%city」也很遠。不過%[0]比%[1]更遠。" } planet { "mars" "saturn" "pluto" } city { "newyork" "moscow" "madrid" } %[i] 為從 0 開始的第 i 次展開結果。 %[ ]在附帶範圍的展開中無法使用。想要再利用附帶範圍展開的過去結果的話,請使用變數。 由於名稱最長一致展開在運行過程中會對展開的對象進行檢索,所以和附帶範圍展開相比,動作速度上會慢上很多。 流程控制 †if的分歧 †式的判定結果為真時則繼續處理{ }内的式子。 request { if !i { "i為0。" } } 可以在後面加入elseif。會在if的判定為偽的時候進行處理。 request { if !i { "i為0。" } elseif i == 5 { "i為5。" } elseif "A" _in_ TOUPPER(i) { "i為字串,並且含有a或A。" } else { "i不是0或5或含有a的字串。" } } if、elseif、else在處理script時若只有一行的話、{ }可省略。因此上述程式碼可寫成如下所示。 request { if !i "i為0。" elseif i == 5 "i為5。" elseif "A" _in_ TOUPPER(i) "i為字串,並且含有a或A。" else "i不是0或5或含有a的字串。" } 但是在if重疊的時候{ }不可省略。以下式子在C語言中是正確的,在文中是錯誤的。 if i == 0 if j == 0 "i和j都是0。" 以下式子的{ }是必要的。 if i == 0 { if j == 0 "i和j都是0。" } 和C語言一様,if的判定式可以用括弧( )將全部式包圍住。 case的分歧 †case可實現條件分歧的構造。 request { case i { when 0 { "i為0。" } when "A" "i為字串A。" others { "i不是0也不是A。" } } } case會實行與判定式結果一致的値所對應的when片段。 when可以用逗號列舉兩個值以上的條件敘述。另外也可以用減號『-』來指定條件的範圍。 request { case name+(i+1) { when "Pentium3","Pentium4" "Pen!!!在1999年發售,而Pen4則在2000年發售。" when "Pentium5"-"PentiumX" { "還沒有。" } others "我不知道。" } } when所記述的條件式必須是即值,不能含有變數或函式、運算子。 when、others在處理script時若只有一行的話,{ }也可像if一樣省略。 switch的分歧 †當你想要自行選取{ }内的輸出候補的話,使用switch的話即可指定輸出候補的位置。 request { switch id { "id為0。" "id為1。" { "id為2。" "id為two。" } "id為3。" } } 會依照變數id的値來指定輸出的字串。指定的值從0開始。 當switch的參考值所對應的候選不在{ }内時輸出空字串。例如說、在上述例子中若id等於100,便會輸出空的字串。 當switch内含有輸出確定子( -- )的時候,會選擇各小組在此值所配對的輸出候補。 request { switch 1 { "かわいい" "天才" "サル" -- "とは言い難い" -- "ですね。" "かもしれません。" } } request的輸出會變成"天才かもしれません。"。 迴圈(loop) †共有while、for、foreach這3種迴圈構造。 while †while是最簡單的迴圈形式,當條件為真時會重複執行{ }内的動作。 request { _i = 1 _j = 0 while _i < 11 { _j += _i _i++ } "將1到10全部加起來的話,可得到%(_j)。" } 上面的例子可以簡單說明while的功能。 下面的例子會產生10個不同的字串。request的輸出結果為報告1~10其中任一個數的平方根的字串。 request { _i = 1 while _i < 11 { "%(_i)的平方根為%(SQRT(_i))。" _i++ } } for †for是與while同様的先判定迴圈構造,其特色在於會在迴圈開始前指定其初期化式、脱出判定式、迴圈執行式。 while的例子用for來寫的話可寫成下面所示。 request { for _i = 1; _i < 11; _i++ { "%(_i)的平方根為%(SQRT(_i))。" } } _i = 1會在迴圈開始前執行。_i < 11為迴圈的條件式、如果條件為真時則迴圈繼續執行。_i++會在迴圈執行完一輪之後、開始新的一輪之前的時候執行。 C語言可用 for ( ; ; ) 作為無限迴圈,文的話各式的省略不可。 for 1;1;1 請這樣子寫。不過,用while的話 while 1 這樣子寫就行了。因此文在製作無限迴圈的時候,不管是從可讀性或是動作速度的角度來看,都建議使用while迴圈。 foreach †照順序取出簡易陣列或泛用陣列的各元素値。 以下例子為取出簡易陣列的元素進行數值的轉換,再將這些數值全部加起來後輸出其結果。 request { _str = "1,3,5,7,9" _t = 0 foreach _str; _i { _t += TOINT(_i) } _t } foreach會持續記述處理對象。上面的例子中foreach指定簡易陣列為_str,然後依次將取出的陣列元素儲存在變數_i中。 即使處理對象的分隔符號被SETDELIM改變了也沒關係,foreach會依照此分隔符號正常的運作。 foreach可處理泛用陣列。 request { _sent = ("I", "am", 31, "years", "old.") _t = "" foreach _sent; _i { _t += (_i + " ") } _t } request會輸出"I am 31 years old. "。 即使在foreach迴圈内將元素取出對象的簡易陣列、泛用陣列進行更改也沒關係。 break †迴圈中出現break的話,會跳出現下實行中最深的迴圈。 request { _j = 0 for _i = 0; _i < 100; _i++ { _j = _i*_i if _j >= 100 break } _i - 1 } 上述的例子中、for為初期値0的_i實行至_i達到100才結束的迴圈。然而,由於迴圈内有被解釋為「_i 的平方值大於等於 100 時便跳脫迴圈」的break存在,因此實際上在 _i = 10 的時候迴圈便會結束了。 request會傳回比_i小1的值,也就是說整個函式request的實際意義為「求平方的結果不超過100的最大整數」。 continue †迴圈中出現continue的時候,會回到迴圈的開頭。 request { _j = "" for _i = 0; _i < 3; _i++ { _j += "go " if _i > 0 continue _j += "ahead " } _j } _i在0、1、2之間變化,當_i等於1、2時continue會被執行,此時_j就不會被追加"ahead "字串。 因此request的輸出會變成"go ahead go go "。 return †return出現時,函式的運行便會在此結束。 to_rad { if GETTYPE(_argv[0]) == 3 { -1 return } _argv[0]*2.0*3.14/360.0 } 函式to_rad會將角度的單位從度轉換為弧(radian)。 預處理(preprocess) †預處理為讀取辭書檔案階段時所執行的命令。 #define †在讀取辭書檔案之前(pass前的)產生的字串進行比對,並且直接將字串置換。 #define before after 在讀入此記述後,若發現before這個字的話會自動置換成after。 #define 的有効範圍從宣告的下一行開始直到這個檔案的終端。 按記述的順序進行置換,寫在前頭的先變換。 #globaldefine †#globaldefine before after 功能與 #define 命令相同,但是兩者的有効範圍不同。 #globaldefine 宣告後,下一行後的全部範圍(也包括之後讀取的辭書檔案)皆有効。也就是說,如果在最初讀取的辭書檔案前頭記述 #globaldefine 的話,其有効範圍即為所有的辭書檔案。 #define會先被處理。#globaldefine 在#define 置換後才被執行。 #globaldefine tea green #define tea milk "teacup" 置換結果為"milkcup"。 預約語 †以下的單字為系統函式名及控制命令名。 TOINT TOREAL TOSTR GETTYPE ISFUNC ISVAR LOGGING GETLASTERROR LOADLIB UNLOADLIB REQUESTLIB CHARSETLIB RAND FLOOR CEIL ROUND SIN COS TAN LOG LOG10 POW SQRT STRSTR STRLEN REPLACE SUBSTR ERASE INSERT TOUPPER TOLOWER CUTSPACE TOBINSTR TOHEXSTR BINSTRTOI HEXSTRTOI CHR FOPEN FCLOSE FREAD FWRITE FWRITE2 FCOPY FMOVE MKDIR RMDIR FDEL FRENAME FSIZE FENUM FCHARSET ARRAYSIZE SETDELIM EVAL ERASEVAR GETTIME GETTICKCOUNT GETMEMINFO RE_SEARCH RE_MATCH RE_GREP SETLASTERROR RE_REPLACE RE_SPLIT RE_GETSTR RE_GETPOS RE_GETLEN CHRCODE ISINTSTR ISREALSTR IARRAY SPLITPATH CVINT CVSTR CVREAL LETTONAME LSO STRFORM ANY SAVEVAR GETSTRBYTES if elseif else case when others switch while for break continue return foreach 以下的單字/文字為運算子。 ( ) [ ] ! ++ -- * / % + - & == != <= >= < > _in_ !_in_ && || = := += -= *= /= %= +:= -:= *:= /:= %:= ,= 謝辞 †以下のライブラリを利用もしくは参考にさせていただきました。感謝致します。
|